from phot_server.utils.phot_logger import logger

from phot_server.rpc.common_data_type.ttypes import PhotError

# the exception code map
exception_code = {
    "FileError": 100,
    "FilePathError": 200,
    "ResourceNotFoundError": 300,
    "ParameterValueError": 400,
    "ParseError": 500,
    "TypeError": 600,
    "GraphInformationError": 700,
    "IdDuplicationException": 800,
    "TemporaryResourceException": 900,
    "ConversionError": 10000,
    "ModuleAnalysisError": 11000,
    "DispatcherError": 12000,
    "ArithmeticUnitError": 13000,
    "VerificationError": 14000,
    "ComputationalGraphGenerationError": 15000,
    "EngineError": 16000,
    "RunOutOfTime": 17000
}


class FileError(Exception):
    """
    if the file construction had been broken, raise this error
    """
    pass


class FilePathError(Exception):
    """
    if file path is None or incorrect, raise this error
    """
    pass


class ResourceNotFoundError(Exception):
    """
    if there is no target resource, raise this error
    """

    def __init__(self, object_class=None, object_id=None, container_class=None, container_id=None, message=None):
        if message is not None:
            exception_string = message
        else:
            exception_string = construct_exception_string("is not found", object_class, object_id, container_class,
                                                          container_id)
        super(ResourceNotFoundError, self).__init__(exception_string)


class ParameterValueError(Exception):
    """
    if there is some error in resource, raise this error
    """
    pass


class ParseError(Exception):
    """
    if there are some error in parsing xml or toml, raise this error
    """
    pass


class GraphInformationError(Exception):
    """
        if there are some error in GraphInformation, raise this error
    """
    pass


class IdDuplicationException(Exception):
    """
            if the object id is repetition, raise this error
    """

    def __init__(self, object_class=None, object_id=None, container_class=None, container_id=None):
        super(IdDuplicationException, self).__init__(
            construct_exception_string("is duplicated", object_class, object_id, container_class, container_id))


class TemporaryResourceException(Exception):
    def __init__(self, resource_name):
        super(TemporaryResourceException, self).__init__(
            "Resource '{}' is temporary and should be saved as...".format(resource_name))


class ResourceIsUpdatedException(Exception):
    def __init__(self, resource_name):
        super(ResourceIsUpdatedException, self).__init__(
            "Resource '{}' is updated and do you want to ignore changes?".format(resource_name))

class Grid2dPlotException(Exception):
    def __init__(self, grid, axis):
        super(Grid2dPlotException, self).__init__("Grid {} is 2D grid with shape ({},{},{}). You can not plot its {} axis figure."
                                                  .format(grid.gridId, grid.xLength, grid.yLength, grid.zLength, axis))

def construct_exception_string(predicate: str, object_class=None, object_id=None, container_class=None,
                               container_id=None):
    exception_string = ""
    if object_class is not None:
        exception_string += "{}".format(object_class)
    if object_id is not None:
        exception_string += " with id '{}'".format(object_id)
    exception_string += " " + predicate
    if container_class is not None:
        exception_string += " in".format(container_class)
    if container_id is not None:
        exception_string += " with id '{}'".format(container_id)
    exception_string += "."
    return exception_string


# turn error to PhotError
def to_PhotError(error):
    error_name = error.__class__.__name__
    # get error code
    code = exception_code.get(error_name, 9999)
    message = str(error)
    return PhotError(code, error_name, message)
